package com.h3c.nem.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eos.common.domain.ActiveUser;
import com.h3c.nem.bo.EmailAttachmentBO;
import com.h3c.nem.bo.SendEmailBO;
import com.h3c.nem.client.AbilityClient;
import com.h3c.nem.config.SpringUtil;
import com.h3c.nem.config.properties.EmailAttachmentProperties;
import com.h3c.nem.config.properties.TbOfferWorkerProperties;
import com.h3c.nem.dto.GenerateOfferDTO;
import com.h3c.nem.dto.SendEmailDTO;
import com.h3c.nem.entity.*;
import com.h3c.nem.enums.OfferWorkerOfferStatusEnum;
import com.h3c.nem.enums.OfferWorkerStatusEnum;
import com.h3c.nem.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenyifan
 * @date 2022/6/14 16:29
 */
@Slf4j
@Component
public class EmailUtil {

    private static ITbOfferCompanyRelaService companyRelaService;

    private static ISdEmailTemplateService emailTemplateService;

    private static ITbOfferWorkerService offerWorkerService;

    private static ITbOfferSendRecordService offerSendRecordService;

    private static AbilityClient abilityClient;

    private static EmailAttachmentProperties attachmentProperties;

    private static TbOfferWorkerProperties offerWorkerProperties;

    private static ISdDeptService sdDeptService;

    @Autowired
    public void setSdDeptService(ISdDeptService sdDeptService) {
        EmailUtil.sdDeptService = sdDeptService;
    }

    @Autowired
    public void setAttachmentProperties(EmailAttachmentProperties attachmentProperties) {
        EmailUtil.attachmentProperties = attachmentProperties;
    }

    @Autowired
    public void setCompanyRelaService(ITbOfferCompanyRelaService companyRelaService) {
        EmailUtil.companyRelaService = companyRelaService;
    }

    @Autowired
    public void setEmailTemplateService(ISdEmailTemplateService emailTemplateService) {
        EmailUtil.emailTemplateService = emailTemplateService;
    }

    @Autowired
    public void setOfferWorkerService(ITbOfferWorkerService offerWorkerService) {
        EmailUtil.offerWorkerService = offerWorkerService;
    }

    @Autowired
    public void setAbilityClient(AbilityClient abilityClient) {
        EmailUtil.abilityClient = abilityClient;
    }

    @Autowired
    public void setOfferSendRecordService(ITbOfferSendRecordService offerSendRecordService) {
        EmailUtil.offerSendRecordService = offerSendRecordService;
    }

    @Autowired
    public void setOfferWorkerProperties(TbOfferWorkerProperties offerWorkerProperties) {
        EmailUtil.offerWorkerProperties = offerWorkerProperties;
    }

    /**
     * 加密工号（其他的类中应避免出现同名）
     */
    public static final String ENCRYPTED_WORKER_ID = "encryptedWorkerId";

    /**
     * 填充邮件内容（有薪资内容）
     *
     * @param generateOfferDTO 生成内容的参数
     * @param salaryParams     薪资参数
     * @return
     */
    public static Map<String, String> fixUpContent(GenerateOfferDTO generateOfferDTO,
                                                   Map<String, String> salaryParams) {
        Optional.ofNullable(generateOfferDTO.getWorkerId()).orElseThrow(() -> new IllegalArgumentException(generateOfferDTO.getWorkerId()));
        SdAllWorker sdAllWorker = SpringUtil.getBean(ISdAllWorkerService.class).getById(generateOfferDTO.getOfferContactor());
        generateOfferDTO.setOfferContactor(sdAllWorker.getWorkerName() + "/" + sdAllWorker.getWorkerId());
        generateOfferDTO.setOfferContactorPhone(sdAllWorker.getPhoneNo());
        generateOfferDTO.setOfferContactorEmail(sdAllWorker.getEmail());
        TbOfferWorker offerWorker = offerWorkerService.getById(generateOfferDTO.getWorkerId());
        log.info("offerworker:{}", offerWorker.getPersonnelRangeCode());
        String templateId = companyRelaService.getOne(new QueryWrapper<TbOfferCompanyRela>().lambda()
                .eq(TbOfferCompanyRela::getCompanyCode, offerWorker.getPersonnelRangeCode())
        ).getTemplateId();
        SdEmailTemplate emailTemplate = emailTemplateService.getById(templateId);
        String templateContent = emailTemplate.getEmailTemplateContent();
        List<String> matchPattern = ReUtils.getMatchPattern(templateContent, ReUtils.GET_REPLACE_PATTERN);
        for (String s : matchPattern) {
            String fieldName = s.substring(2, s.length() - 1);
            if (salaryParams.keySet().contains(fieldName)) {
                continue;
            }
            Object fieldValue = null;
            if (fieldName.equals(ENCRYPTED_WORKER_ID)) {
                fieldValue = EncryptionUtil.getEncryptDataAES(String.valueOf(ReflectUtil.getFieldValue(offerWorker, "workerId")));
            } else {
                if (ReflectUtil.hasField(TbOfferWorker.class, fieldName)) {
                    fieldValue = ReflectUtil.getFieldValue(offerWorker, fieldName);
                } else if (ReflectUtil.hasField(GenerateOfferDTO.class, fieldName)) {
                    fieldValue = ReflectUtil.getFieldValue(generateOfferDTO, fieldName);
                }
            }
            templateContent = StrUtil.replace(templateContent, s, String.valueOf(Optional.ofNullable(fieldValue).orElse("")));
        }
        offerSendRecordService.saveOfferSendRecord(generateOfferDTO, templateContent);
        Map<String, String> result = new HashMap<>(3);
        for (String salaryKey : salaryParams.keySet()) {
            templateContent = templateContent.replaceAll("\\$\\{" + salaryKey + "\\}", salaryParams.get(salaryKey));
        }
        result.put("emailContent", templateContent);
        result.put("subject", emailTemplate.getEmailTemplateTitle());
        return result;
    }

    /**
     * 发送offer邮件
     *
     * @param sendEmailDTO
     */
    public static void sendOfferPtEmail(SendEmailDTO sendEmailDTO) {
        TbOfferWorker offerWorker = offerWorkerService.getById(sendEmailDTO.getWorkerId());
        if (offerWorker.getDataSource().equals("BPM") && offerWorker.getWorkerStatus().getCode() < OfferWorkerStatusEnum.待签合同.getCode()) {
            List<EmailAttachmentProperties.EmailAttachmentNacosPro> fileSfsList;
            List<EmailAttachmentBO> attachmentBOList = new ArrayList<>();
            List<File> fileList = new ArrayList<>();
            if ("报到后先参加文化培训".equals(sendEmailDTO.getRegisterMode())) {
                fileSfsList = attachmentProperties.getCulturalTraining();
            } else if (sendEmailDTO.getRegisterPlace().equals(EmailAttachmentProperties.Fields.beiJing.name())) {
                fileSfsList = attachmentProperties.getBeiJing();
            } else if (sendEmailDTO.getRegisterPlace().equals(EmailAttachmentProperties.Fields.hangZhou.name())) {
                fileSfsList = attachmentProperties.getHangZhou();
            } else {
                fileSfsList = attachmentProperties.getOffice();
            }
            for (EmailAttachmentProperties.EmailAttachmentNacosPro attachmentNacosPro : fileSfsList) {
                JSONObject result = abilityClient.downloadFile(attachmentNacosPro.getSfsId(), "入职附件.docx", offerWorkerProperties.getDownloadSfsAccount());
                String fileBase64 = result.getJSONObject("data").getString("file");
                File temp = FileUtil.writeBytes(Base64.decode(fileBase64), EmailUtil.class.getResource("/").toString() + "/temp/email/" + IdUtil.randomUUID() + ".docx");
                if (!"报到后先参加文化培训".equals(sendEmailDTO.getRegisterMode()) &&
                        sendEmailDTO.getRegisterPlace().equals(EmailAttachmentProperties.Fields.office.name())) {
                    HashMap<String, String> param = new HashMap<>(3);
                    param.put("officeContactor", sendEmailDTO.getOfficeContactor());
                    param.put("officePhone", sendEmailDTO.getOfficePhone());
                    param.put("officeAddress", sendEmailDTO.getOfficeAddress());
                    String fixupFilePath = EmailUtil.class.getResource("/").toString() + "/temp/email/" + IdUtil.randomUUID() + ".docx";
                    File fixupFile = FileUtil.touch(fixupFilePath);
                    WordUtil.replaceTemplateWrite(temp.getAbsolutePath(), param, fixupFile);
                    FileUtil.del(temp);
                    temp = fixupFile;
                }
                fileList.add(temp);
                EmailAttachmentBO attachmentBO = new EmailAttachmentBO();
                attachmentBO.setAttachment(Base64.encode(FileUtil.readBytes(temp)));
                attachmentBO.setAttachmentName(attachmentNacosPro.getAttachmentName());
                attachmentBOList.add(attachmentBO);
            }
            SendEmailBO sendEmailBO = new SendEmailBO();
            sendEmailBO.setContent(sendEmailDTO.getEmailContent());
            sendEmailBO.setToEmail(offerWorker.getEmail());
            sendEmailBO.setSubject(sendEmailDTO.getSubject());
            sendEmailBO.setAttachmentBOList(attachmentBOList);
            sendEmailBO.setAppId("nem-manager");
            sendEmailBO.setIsRecord(false);
            sendEmailBO.setOperator(StringUtils.hasText(CommonUtil.getActivUser().getAccount()) ? CommonUtil.getActivUser().getAccount() : "-1");
            Map<String, String> stringStringMap = abilityClient.sendEmail(sendEmailBO);
            if ("success".equals(stringStringMap.get("state"))) {
                offerSendRecordService.updateOfferSendRecord(sendEmailDTO.getWorkerId(), fileList);
                if (offerWorker.getWorkerStatus().getCode() < OfferWorkerStatusEnum.待填写入职资料.getCode()) {
                    offerWorker.setWorkerStatus(OfferWorkerStatusEnum.待填写入职资料);
                }
                try {
                    if (offerWorker.getPlanReportDate() == null) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        Date parse = sdf.parse(sendEmailDTO.getRegisterDate());
                        offerWorker.setPlanReportDate(parse);
                    }
                } catch (Exception e) {
                    log.error("{}日期{} 转换异常",sendEmailDTO.getWorkerId(),sendEmailDTO.getRegisterDate());
                }
                offerWorkerService.updateById(offerWorker.setOfferStatus(OfferWorkerOfferStatusEnum.SEND_OFFER));
                return;
            }
            throw new AppBusinessException("公共平台发送邮件失败,请稍后重试");
        }
        throw new AppBusinessException("当前员工状态无法再次发放offer");
    }

    /**
     * 获取邮件模板内容
     *
     * @param emailTemplateId
     * @return
     */
    public static String getEmailTemplateContent(String emailTemplateId, Map<String, String> param) {
        String emailTemplateContent = emailTemplateService.getById(emailTemplateId).getEmailTemplateContent();
        if (Objects.nonNull(param)) {
            List<String> matchPattern = ReUtils.getMatchPattern(emailTemplateContent, ReUtils.GET_REPLACE_PATTERN);
            for (String s : matchPattern) {
                String fieldName = s.substring(2, s.length() - 1);
                String fieldValue = param.get(fieldName);
                emailTemplateContent = emailTemplateContent.replaceAll(makeQueryStringAllRegExp(s), Optional.ofNullable(fieldValue).orElse(""));
            }
        }
        return emailTemplateContent;
    }

    /**
     * 转义正则特殊字符 （$()*+.[]?\^{}
     * \\需要第一个替换，否则replace方法替换时会有逻辑bug
     *
     * @param str
     * @return
     */
    public static String makeQueryStringAllRegExp(String str) {
        if (StringUtils.isEmpty(str)) {
            return str;
        }
        return str.replace("\\", "\\\\").replace("*", "\\*")
                .replace("+", "\\+").replace("|", "\\|")
                .replace("{", "\\{").replace("}", "\\}")
                .replace("(", "\\(").replace(")", "\\)")
                .replace("^", "\\^").replace("$", "\\$")
                .replace("[", "\\[").replace("]", "\\]")
                .replace("?", "\\?").replace(",", "\\,")
                .replace(".", "\\.").replace("&", "\\&");
    }

    /**
     * 调用公共平台发送邮件接口发送邮件
     *
     * @param emailTemplateId  邮件模板编码
     * @param receiveEmail     收件人邮箱（,分隔）
     * @param subject          邮件主题
     * @param attachmentBOList 附件列表
     * @param isRecord         是否记录内容 false不记录 不传或者传true则记录
     */
    public static void sendPtEmail(String emailTemplateId, Map<String, String> param, String receiveEmail, String subject, List<EmailAttachmentBO> attachmentBOList, Boolean isRecord) {
        try {
            SendEmailBO sendEmailBO = new SendEmailBO();
            sendEmailBO.setContent(getEmailTemplateContent(emailTemplateId, param));
            sendEmailBO.setToEmail(receiveEmail);
            sendEmailBO.setSubject(subject);
            sendEmailBO.setIsRecord(isRecord);
            sendEmailBO.setAppId("nem-manager");
            if (Objects.isNull(attachmentBOList)) {
                sendEmailBO.setAttachmentBOList(new ArrayList<>());
            } else {
                sendEmailBO.setAttachmentBOList(attachmentBOList);
            }
            ActiveUser user = CommonUtil.getActivUser();
            if (Objects.nonNull(user)) {
                sendEmailBO.setOperator(StringUtils.hasText(user.getAccount()) ? CommonUtil.getActivUser().getAccount() : "-1");
            } else {
                sendEmailBO.setOperator("-1");
            }
            Map<String, String> stringStringMap = abilityClient.sendEmail(sendEmailBO);
            if ("success".equals(stringStringMap.get("state"))) {
                return;
            }
        } catch (Exception e) {
            log.error("公共平台发送邮件失败,请稍后重试", e.getMessage());
        }
    }

    /**
     * 根据预备员工Id获取收件人邮箱
     *
     * @param workerId      预备员工id
     * @param needSSC       是否发送给ssc管理员
     * @param needBP        是否发送给bp
     * @param needContactor 是否发送给接口人
     * @param needContactor 是否发送给预备员工
     * @return
     */
    public static String getReceiveEmail(String workerId, Boolean needSSC, Boolean needBP, Boolean needContactor, Boolean needWorker) {
        ArrayList<String> receiveEmailList = new ArrayList<>();
        TbOfferWorker offerWorker = offerWorkerService.getById(workerId);
        if (needWorker) {
            if (StringUtils.hasText(offerWorker.getEmail())) {
                receiveEmailList.add(offerWorker.getEmail());
            }
        }
        if (needSSC) {
            SdDept sdDept = sdDeptService.getDeptByNameChain(offerWorker.getDeptNameChain());
            String sscManagerWorkerIds = sdDept.getOfferDeptManagerId();
            List<String> sscManagerEmailList = sdDeptService.getEmailList(sscManagerWorkerIds);
            receiveEmailList.addAll(sscManagerEmailList);
        }
        if (needBP) {
            String bpWorkerIds = sdDeptService.getBpByDeptNameChain(offerWorker.getDeptNameChain());
            List<String> bpEmailList = sdDeptService.getEmailList(bpWorkerIds);
            receiveEmailList.addAll(bpEmailList);
        }
        if (needContactor) {
            String contactorWorkerIds = sdDeptService.getContactorByDeptNameChain(offerWorker.getDeptNameChain(), offerWorker.getWorkCity());
            List<String> contactorEmailList = sdDeptService.getEmailList(contactorWorkerIds);
            receiveEmailList.addAll(contactorEmailList);
        }
        return receiveEmailList.stream().distinct().collect(Collectors.joining(","));
    }
}
